package com.party.core.service.member.biz;

import com.party.common.utils.StringUtils;
import com.party.core.model.member.MemberPersonalCount;
import com.party.core.model.member.PartnerMember;
import com.party.core.api.crowdfund.IProjectService;
import com.party.core.api.crowdfund.ISupportService;
import com.party.core.api.distributor.IDistributorRelationService;
import com.party.core.api.member.IMemberActService;
import com.party.core.service.member.IMemberPersonalCountService;
import com.party.core.service.member.IPartnerMemberService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 个人数据统计业务
 * @Author: yangshoukun
 * @Date: 2018/3/1 17:15
 */
@Service
public class MemberPersonalCountBizService {
    @Autowired
    private IMemberPersonalCountService memberPersonalCountService;
    @Autowired
    private IPartnerMemberService partnerMemberService;
    @Autowired
    private IMemberActService memberActService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private IDistributorRelationService distributorRelationService;
    @Autowired
    private ISupportService supportService;

    // 初始化
    private static final int STATUS_INIT = 0;
    // 矫正(只矫正昨天的数据)
//    private static final int STATUS_CHECK = 1;

    private static Logger logger = LoggerFactory.getLogger(MemberPersonalCountBizService.class);

    /**
     * 实时更新活动报名数量
     * @param partnerId
     * @param memberId
     */
    public void updateActivityNum(String partnerId, String memberId, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setActivityNum(0);
        } else if (null == memberPersonalCount.getActivityNum()) {
            memberPersonalCount.setActivityNum(0);
        }
        memberPersonalCount.setActivityNum(add ? memberPersonalCount.getActivityNum() + 1 : memberPersonalCount.getActivityNum() - 1);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 实时更新活动报名金额
     * @param partnerId
     * @param memberId
     */
    public void updateActivityMoney(String partnerId, String memberId, double money, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setActivityMoney(BigDecimal.valueOf(0));
        } else if (null == memberPersonalCount.getActivityMoney()) {
            memberPersonalCount.setActivityMoney(BigDecimal.valueOf(0));
        }
        BigDecimal m = memberPersonalCount.getActivityMoney();
        if (add) {
            m = m.add(BigDecimal.valueOf(money));
        } else {
            m = m.subtract(BigDecimal.valueOf(money));
        }
        memberPersonalCount.setActivityMoney(m);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 实时更新众筹数量
     * @param partnerId
     * @param memberId
     */
    public void updateCrowdfundNum(String partnerId, String memberId, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setCrowdfundNum(0);
        } else if (null == memberPersonalCount.getCrowdfundNum()) {
            memberPersonalCount.setCrowdfundNum(0);
        }
        memberPersonalCount.setCrowdfundNum(add ? memberPersonalCount.getCrowdfundNum() + 1 : memberPersonalCount.getCrowdfundNum() - 1);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 实时更新众筹报名金额
     * @param partnerId
     * @param memberId
     */
    public void updateCrowdfundMoney(String partnerId, String memberId, double money, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setCrowdfundMoney(BigDecimal.valueOf(0));
        } else if (null == memberPersonalCount.getCrowdfundMoney()) {
            memberPersonalCount.setCrowdfundMoney(BigDecimal.valueOf(0));
        }
        BigDecimal m = memberPersonalCount.getCrowdfundMoney();
        if (add) {
            m = m.add(BigDecimal.valueOf(money));
        } else {
            m = m.subtract(BigDecimal.valueOf(money));
        }
        memberPersonalCount.setCrowdfundMoney(m);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 实时更新联合发起数量
     * @param partnerId
     * @param memberId
     */
    public void updateRepresentNum(String partnerId, String memberId) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setRepresentNum(0);
        } else if (null == memberPersonalCount.getRepresentNum()) {
            memberPersonalCount.setRepresentNum(0);
        }
        memberPersonalCount.setRepresentNum(memberPersonalCount.getRepresentNum() + 1);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 实时更新支持金额
     * @param partnerId
     * @param memberId
     */
    public void updateSupportMoney(String partnerId, String memberId, double money, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setSupportMoney(BigDecimal.valueOf(0));
        } else if (null == memberPersonalCount.getSupportMoney()) {
            memberPersonalCount.setSupportMoney(BigDecimal.valueOf(0));
        }
        BigDecimal m = memberPersonalCount.getSupportMoney();
        if (add) {
            m = m.add(BigDecimal.valueOf(money));
        } else {
            m = m.subtract(BigDecimal.valueOf(money));
        }
        memberPersonalCount.setSupportMoney(m);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 同时更新支持和众筹金额
     * @param partnerId
     * @param memberId
     * @param money
     * @param add
     */
    public void updateCrowdfundSupportMoney(String partnerId, String memberId, double money, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setCrowdfundMoney(BigDecimal.valueOf(0));
            memberPersonalCount.setSupportMoney(BigDecimal.valueOf(0));
        }
        if (null == memberPersonalCount.getCrowdfundMoney()) {
            memberPersonalCount.setCrowdfundMoney(BigDecimal.valueOf(0));
        }
        if (null == memberPersonalCount.getSupportMoney()) {
            memberPersonalCount.setSupportMoney(BigDecimal.valueOf(0));
        }
        BigDecimal crowdfund = memberPersonalCount.getCrowdfundMoney();
        BigDecimal support = memberPersonalCount.getSupportMoney();
        if (add) {
            crowdfund = crowdfund.add(BigDecimal.valueOf(money));
            support = support.add(BigDecimal.valueOf(money));
        } else {
            crowdfund = crowdfund.subtract(BigDecimal.valueOf(money));
            support = support.subtract(BigDecimal.valueOf(money));
        }
        memberPersonalCount.setCrowdfundMoney(crowdfund);
        memberPersonalCount.setSupportMoney(support);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 同时更新活动的数量和金额
     * @param partnerId
     * @param memberId
     * @param money
     * @param add
     */
    public void updateActivityNumMoney(String partnerId, String memberId, double money, boolean add) {
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setActivityMoney(BigDecimal.valueOf(0));
            memberPersonalCount.setActivityNum(0);
        }
        if (null == memberPersonalCount.getActivityMoney()) {
            memberPersonalCount.setActivityMoney(BigDecimal.valueOf(0));
        }
        if (null == memberPersonalCount.getActivityNum()) {
            memberPersonalCount.setActivityNum(0);
        }
        BigDecimal m = memberPersonalCount.getActivityMoney();
        if (add) {
            m = m.add(BigDecimal.valueOf(money));
        } else {
            m = m.subtract(BigDecimal.valueOf(money));
        }
        memberPersonalCount.setActivityMoney(m);
        memberPersonalCount.setActivityNum(add ? memberPersonalCount.getActivityNum() + 1 : memberPersonalCount.getActivityNum() - 1);
        insertUpdate(memberId, partnerMemberId, memberPersonalCount);
    }

    /**
     * 内部使用的插入或者更新(不和外部使用同一个方法, 避免快速调用同一个sql两次)
     * @param memberId
     * @param partnerMemberId
     * @param memberPersonalCount
     * @return
     */
    private boolean insertUpdate(String memberId, String partnerMemberId, MemberPersonalCount memberPersonalCount) {
        if (StringUtils.isEmpty(memberPersonalCount.getId())) {
            // 没有主键, 插入
            memberPersonalCount.setMemberId(memberId);
            memberPersonalCount.setPartnerMemberId(partnerMemberId);
            memberPersonalCountService.insert(memberPersonalCount);
        } else {
            // 有主键, 更新
            memberPersonalCountService.update(memberPersonalCount);
        }
        return true;
    }

    /**
     * 插入或者更新数据
     * @param partnerId
     * @param memberId
     * @param memberPersonalCount
     */
    public boolean insertMemberCount(String partnerId, String memberId, MemberPersonalCount memberPersonalCount) {

        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (null == partnerMemberId) {
            return false;
        }

        MemberPersonalCount oldMemberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == oldMemberPersonalCount) {
            // 没有找到就插入
            memberPersonalCount.setMemberId(memberId);
            memberPersonalCount.setPartnerMemberId(partnerMemberId);
            memberPersonalCountService.insert(memberPersonalCount);
        } else {
            // 找到了就更新
            boolean changed = haveChange(oldMemberPersonalCount, memberPersonalCount);
            if (changed) {
                copyMemberPersonalCount(memberPersonalCount, oldMemberPersonalCount);

                memberPersonalCountService.update(oldMemberPersonalCount);
            }
        }
        return true;
    }

    private boolean haveChange(MemberPersonalCount memberPersonalCountOld, MemberPersonalCount memberPersonalCountNew) {
        if (memberPersonalCountNew.getActivityNum() != null && !memberPersonalCountOld.getActivityNum().equals(memberPersonalCountNew.getActivityNum())) {
            return true;
        }
        if (memberPersonalCountNew.getActivityMoney() != null && !memberPersonalCountOld.getActivityMoney().equals(memberPersonalCountNew.getActivityMoney())) {
            return true;
        }
        if (memberPersonalCountNew.getCrowdfundMoney() != null && !memberPersonalCountOld.getCrowdfundMoney().equals(memberPersonalCountNew.getCrowdfundMoney())) {
            return true;
        }
        if (memberPersonalCountNew.getCrowdfundNum() != null && !memberPersonalCountOld.getCrowdfundNum().equals(memberPersonalCountNew.getCrowdfundNum())) {
            return true;
        }
        if (memberPersonalCountNew.getRepresentNum() != null && !memberPersonalCountOld.getRepresentNum().equals(memberPersonalCountNew.getRepresentNum())) {
            return true;
        }
        if (memberPersonalCountNew.getSupportMoney() != null && !memberPersonalCountOld.getSupportMoney().equals(memberPersonalCountNew.getSupportMoney())) {
            return true;
        }
        return false;
    }

    private String getPartnerMemberId(String partnerId, String memberId) {
        PartnerMember partnerMember = new PartnerMember();
        partnerMember.setMemberId(memberId);
        partnerMember.setPartnerId(partnerId);
        List<PartnerMember> list = partnerMemberService.listPage(partnerMember, null);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0).getId();
    }

    private void copyMemberPersonalCount(MemberPersonalCount memberPersonalCount, MemberPersonalCount oldMemberPersonalCount) {
        if (memberPersonalCount.getActivityNum() != null) {
            oldMemberPersonalCount.setActivityNum(memberPersonalCount.getActivityNum());
        }
        if (memberPersonalCount.getActivityMoney() != null) {
            oldMemberPersonalCount.setActivityMoney(memberPersonalCount.getActivityMoney());
        }
        if (memberPersonalCount.getCrowdfundNum() != null) {
            oldMemberPersonalCount.setCrowdfundNum(memberPersonalCount.getCrowdfundNum());
        }
        if (memberPersonalCount.getCrowdfundMoney() != null) {
            oldMemberPersonalCount.setCrowdfundMoney(memberPersonalCount.getCrowdfundMoney());
        }
        if (memberPersonalCount.getRepresentNum() != null) {
            oldMemberPersonalCount.setRepresentNum(memberPersonalCount.getRepresentNum());
        }
        if (memberPersonalCount.getSupportMoney() != null) {
            oldMemberPersonalCount.setSupportMoney(memberPersonalCount.getSupportMoney());
        }
    }

    public MemberPersonalCount getSet(String partnerId, String memberId) {
        if (StringUtils.isEmpty(partnerId) || StringUtils.isEmpty(memberId)) {
            return null;
        }
        String partnerMemberId = getPartnerMemberId(partnerId, memberId);
        if (StringUtils.isEmpty(partnerMemberId)) {
            return null;
        }
        MemberPersonalCount memberPersonalCount = memberPersonalCountService.getByPartnerMemberId(partnerMemberId);
        if (null == memberPersonalCount) {
            memberPersonalCount = new MemberPersonalCount();
            memberPersonalCount.setPartnerMemberId(partnerMemberId);
            memberPersonalCount.setMemberId(memberId);
            memberPersonalCountService.insert(memberPersonalCount);
        }
        return memberPersonalCount;
    }

    /**
     * 一个人的数据统计
     * @param partnerMember
     */
    public void countOne(PartnerMember partnerMember) {
        CountEntity entity = new CountEntity();
        // 某人在某机构下的活动报名数量和金额
        oneMemberActCount(partnerMember, entity);
        // 某人在某机构下的众筹报名数量和金额
        oneMemberZcCount(partnerMember, entity);
        // 某人在某机构下的联合发起数量(活动和众筹)
        oneMemberRepresentCount(partnerMember, entity);
        // 某人在某机构下的支持金额
        oneMemberSupportCount(partnerMember, entity);

        MemberPersonalCount memberPersonalCount = new MemberPersonalCount();
        memberPersonalCount.setPartnerMemberId(partnerMember.getId());
        memberPersonalCount.setMemberId(partnerMember.getMemberId());
        memberPersonalCount.setActivityMoney(null == entity.getActivityMoney() ? BigDecimal.valueOf(0) : entity.getActivityMoney());
        memberPersonalCount.setActivityNum(null == entity.getActivityNum() ? 0 : entity.getActivityNum());
        memberPersonalCount.setCrowdfundMoney(null == entity.getCrowdfundMoney() ? BigDecimal.valueOf(0) : entity.getCrowdfundMoney());
        memberPersonalCount.setCrowdfundNum(null == entity.getCrowdfundNum() ? 0 : entity.getCrowdfundNum());
        memberPersonalCount.setRepresentNum(null == entity.getRepresentNum() ? 0 : entity.getRepresentNum());
        memberPersonalCount.setSupportMoney(null == entity.getSupportMoney() ? BigDecimal.valueOf(0) : entity.getSupportMoney());

        insertMemberCount(partnerMember.getPartnerId(), partnerMember.getMemberId(), memberPersonalCount);
    }

    /**
     * 某人在某机构下的活动报名数量和金额
     * @param partnerMember
     */
    private CountEntity oneMemberActCount(PartnerMember partnerMember, CountEntity entity) {
        List<Map<String, Object>> list = memberActService.getAllSuccessGroupAPI(STATUS_INIT, partnerMember.getPartnerId(), partnerMember.getMemberId());
        if (CollectionUtils.isEmpty(list)) {
            return entity;
        }
        List<CountEntity> entities = list.stream().map(map -> {
            /*entity.setPartnerId(map.get("partnerId") == null ? null : map.get("partnerId").toString());
            entity.setMemberId(map.get("memberId") == null ? null : map.get("memberId").toString());
            Date date = map.get("createDate") == null ? null : DateUtils.convertDate(map.get("createDate").toString());
            if (entity.getCreateDate() == null || (date != null && entity.getCreateDate().getTime() > date.getTime())) {
                entity.setCreateDate(date);
            }*/
            entity.setActivityNum(map.get("activityNum") == null ? null : Integer.parseInt(map.get("activityNum").toString()));
            entity.setActivityMoney(map.get("activityMoney") == null ? null : BigDecimal.valueOf(Double.valueOf(map.get("activityMoney").toString())));
            return entity;
        }).collect(Collectors.toList());
        return entity;
    }

    /**
     * 某人在某机构下的众筹报名数量和金额
     * @param partnerMember
     */
    private CountEntity oneMemberZcCount(PartnerMember partnerMember, CountEntity entity) {
        List<Map<String, Object>> list = projectService.getAllGroupAPI(STATUS_INIT, partnerMember.getPartnerId(), partnerMember.getMemberId());
        if (CollectionUtils.isEmpty(list)) {
            return entity;
        }
        List<CountEntity> entities = list.stream().map(map -> {
            /*entity.setPartnerId(map.get("partnerId") == null ? null : map.get("partnerId").toString());
            entity.setMemberId(map.get("memberId") == null ? null : map.get("memberId").toString());
            Date date = map.get("createDate") == null ? null : DateUtils.convertDate(map.get("createDate").toString());
            if (entity.getCreateDate() == null || (date != null && entity.getCreateDate().getTime() > date.getTime())) {
                entity.setCreateDate(date);
            }*/
            entity.setCrowdfundNum(map.get("crowdfundNum") == null ? null : Integer.parseInt(map.get("crowdfundNum").toString()));
            entity.setCrowdfundMoney(map.get("crowdfundMoney") == null ? null : BigDecimal.valueOf(Double.valueOf(map.get("crowdfundMoney").toString())));
            return entity;
        }).collect(Collectors.toList());
        return entity;
    }

    /**
     * 某人在某机构下的联合发起数量(活动和众筹)
     * @param partnerMember
     * @param entity
     * @return
     */
    private CountEntity oneMemberRepresentCount(PartnerMember partnerMember, CountEntity entity) {
        List<Map<String, Object>> list = distributorRelationService.getAllGroupAPI(STATUS_INIT, partnerMember.getPartnerId(), partnerMember.getMemberId());
        if (CollectionUtils.isEmpty(list)) {
            return entity;
        }
        List<CountEntity> entities = list.stream().map(map -> {
            /*entity.setPartnerId(map.get("partnerId") == null ? null : map.get("partnerId").toString());
            entity.setMemberId(map.get("memberId") == null ? null : map.get("memberId").toString());
            Date date = map.get("createDate") == null ? null : DateUtils.convertDate(map.get("createDate").toString());
            if (entity.getCreateDate() == null || (date != null && entity.getCreateDate().getTime() > date.getTime())) {
                entity.setCreateDate(date);
            }*/
            entity.setRepresentNum(map.get("representNum") == null ? null : Integer.parseInt(map.get("representNum").toString()));
            return entity;
        }).collect(Collectors.toList());
        return entity;
    }

    /**
     * 某人在某机构下的支持金额
     * @param partnerMember
     * @param entity
     * @return
     */
    private CountEntity oneMemberSupportCount(PartnerMember partnerMember, CountEntity entity) {
        List<Map<String, Object>> list = supportService.getAllGroupAPI(STATUS_INIT, partnerMember.getPartnerId(), partnerMember.getMemberId());
        if (CollectionUtils.isEmpty(list)) {
            return entity;
        }
        List<CountEntity> entities = list.stream().map(map -> {
            /*entity.setPartnerId(map.get("partnerId") == null ? null : map.get("partnerId").toString());
            entity.setMemberId(map.get("memberId") == null ? null : map.get("memberId").toString());
            Date date = map.get("createDate") == null ? null : DateUtils.convertDate(map.get("createDate").toString());
            if (entity.getCreateDate() == null || (date != null && entity.getCreateDate().getTime() > date.getTime())) {
                entity.setCreateDate(date);
            }*/
            entity.setSupportMoney(map.get("supportMoney") == null ? null : BigDecimal.valueOf(Double.valueOf(map.get("supportMoney").toString())));
            return entity;
        }).collect(Collectors.toList());
        return entity;
    }

    class CountEntity {
        // 会员id
        private String memberId;
        // 机构id
        private String partnerId;
        // 时间
        private Date createDate;
        // 活动费用
        private BigDecimal activityMoney;
        // 活动数量
        private Integer activityNum;
        // 众筹费用
        private BigDecimal crowdfundMoney;
        // 众筹数量
        private Integer crowdfundNum;
        // 联合发起数量(包括活动和众筹)
        private Integer representNum;
        // 众筹支持金额
        private BigDecimal supportMoney;

        public String getMemberId() {
            return memberId;
        }

        public void setMemberId(String memberId) {
            this.memberId = memberId;
        }

        public String getPartnerId() {
            return partnerId;
        }

        public void setPartnerId(String partnerId) {
            this.partnerId = partnerId;
        }

        public Date getCreateDate() {
            return createDate;
        }

        public void setCreateDate(Date createDate) {
            this.createDate = createDate;
        }

        public BigDecimal getActivityMoney() {
            return activityMoney;
        }

        public void setActivityMoney(BigDecimal activityMoney) {
            this.activityMoney = activityMoney;
        }

        public Integer getActivityNum() {
            return activityNum;
        }

        public void setActivityNum(Integer activityNum) {
            this.activityNum = activityNum;
        }

        public BigDecimal getCrowdfundMoney() {
            return crowdfundMoney;
        }

        public void setCrowdfundMoney(BigDecimal crowdfundMoney) {
            this.crowdfundMoney = crowdfundMoney;
        }

        public Integer getCrowdfundNum() {
            return crowdfundNum;
        }

        public void setCrowdfundNum(Integer crowdfundNum) {
            this.crowdfundNum = crowdfundNum;
        }

        public Integer getRepresentNum() {
            return representNum;
        }

        public void setRepresentNum(Integer representNum) {
            this.representNum = representNum;
        }

        public BigDecimal getSupportMoney() {
            return supportMoney;
        }

        public void setSupportMoney(BigDecimal supportMoney) {
            this.supportMoney = supportMoney;
        }
    }
}
